/*
 *
 *  * Copyright (c) 2016. For Intelligent Group.
 *
 */

package com.intelligent.ispc.chart.grr;

import com.intelligent.ispc.common.utils.MathUtils;
import com.intelligent.ispc.foundation.chart.AbstractChart;
import com.intelligent.ispc.foundation.chart.axis.FixedNumberAxis;
import com.intelligent.ispc.foundation.chart.util.ChartColor;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.StandardCategoryToolTipGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.data.Range;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.RectangleInsets;

import java.awt.*;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by cherry on 2016/8/31.
 * Modified by QiangChen on 2016/11/7.
 */
public class APlotChart extends AbstractChart {
    private DefaultCategoryDataset dataset;
    private int operator;
    private int part;
    private JFreeChart localChart;
    private double[][] sourceData;
    private String chartName;
    private boolean isDataValid;

    /**
     * Constructor.
     *
     * @param aplotValue chart data.
     * @param operator operator.
     * @param part part.
     */
    public APlotChart(double[][] aplotValue, int operator, int part) {
        this.isDataValid = true;
        this.chartName = "Part by Appraisers Plot";
        this.operator = operator;
        this.part = part;
        this.sourceData = aplotValue;
        dataset = createDataset();
    }

    /**
     * Create dataset for Part by Appraisers Chart, and the abnormal data is processed as necessary.
     *
     * @return return the dataset for plotting.
     */
    public DefaultCategoryDataset createDataset() {
        if (sourceData == null) {
            isDataValid = false;
        } else {
            String[] operatorValue = new String[operator];
            String[] partValue = new String[part];
            dataset = new DefaultCategoryDataset();

            for (int i = 0; i < operator; i++) {
                operatorValue[i] = "Operator" + (i + 1);
            }

            for (int i = 0; i < part; i++) {
                partValue[i] = "Part" + (i + 1);
            }

            for (int i = 0; i < sourceData.length; i++) {
                for (int j = 0; j < sourceData[i].length; j++) {
                    if (Double.isNaN(sourceData[i][j])) {
                        continue;
                    }
                    dataset.addValue(sourceData[i][j], operatorValue[i], partValue[j]);
                }
            }
            return dataset;
        }
        return null;
    }

    @Override
    protected JFreeChart buildChart() {

        if (!isDataValid) {
            return this.blankChart(chartName);
        }

        localChart = ChartFactory.createLineChart("Part by Appraisers Plot", "", "", dataset, PlotOrientation.VERTICAL, true, true, false);
        CategoryPlot localCategoryPlot = (CategoryPlot) localChart.getPlot();
        Color[] colors = new Color[]{ChartColor.BLUE, ChartColor.GREEN, ChartColor.RED, ChartColor.DEGREEN, ChartColor.GRAYBLUE, ChartColor.YELLOW, ChartColor.MAGENTA, ChartColor.NAVY};

        LineAndShapeRenderer localLineAndShapeRenderer = (LineAndShapeRenderer) localCategoryPlot.getRenderer();
        for (int i = 0; i < operator; i++) {
            localLineAndShapeRenderer.setSeriesShapesVisible(i, true);
            localLineAndShapeRenderer.setSeriesLinesVisible(i, true);
            localLineAndShapeRenderer.setSeriesToolTipGenerator(i, new StandardCategoryToolTipGenerator(StandardCategoryToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT_STRING, new DecimalFormat(this.getDigNumFormat())));
            localLineAndShapeRenderer.setSeriesPaint(i, colors[i % colors.length]);
        }
        localLineAndShapeRenderer.setDrawOutlines(true);
        localLineAndShapeRenderer.setUseFillPaint(true);
        localLineAndShapeRenderer.setBaseFillPaint(ChartColor.WHITE);

        FixedNumberAxis axis = new FixedNumberAxis();
        axis.setTickLabelInsets(new RectangleInsets(10, 0, 10, 0));
        List<Double> data = new ArrayList<Double>();
        for (int i = 0; i < sourceData.length; i++) {
            for (int j = 0; j < sourceData[i].length; j++) {
                if (!Double.isNaN(sourceData[i][j])) {
                    data.add(sourceData[i][j]);
                }
            }
        }

        //The maximum and minimum values are calculated to limit the range of Y coordinates.
        double min = 0;
        double max = 0;
        if (data != null && data.size() != 0) {
            min = MathUtils.findMin(data);
            max = MathUtils.findMax(data);
        }
        if (max != min) {
            final double factor = 0.20;
            double reserve = (max - min) * factor;
            axis.setR(new Range(min - reserve, max + reserve));
            localCategoryPlot.setRangeAxis(axis);
        }

        return localChart;
    }
}
